package com.qyl.framework.client.encoder;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import com.qyl.framework.base.Message;
import com.qyl.framework.base.protocol.RequestProto;
import com.qyl.framework.utils.ParamsUtils;

import io.netty.buffer.ByteBuf;
import io.netty.channel.ChannelHandlerContext;
import io.netty.handler.codec.MessageToByteEncoder;

public class RequestProtoEncoder extends MessageToByteEncoder<RequestProto>{

	private static Logger logger = LoggerFactory.getLogger(RequestProtoEncoder.class);
	
	@Override
	protected void encode(ChannelHandlerContext ctx, RequestProto msg, ByteBuf out) {
		logger.info("RequestProtoEncoder encode....");
		try {
			long requestId = msg.getRequestId();
			out.writeLong(requestId);
			logger.info("客户端发送协议id={}", requestId);
			
			String className = msg.getClassName();
			byte[] classNameBytes = className.getBytes();
			out.writeByte(classNameBytes.length);
			out.writeBytes(classNameBytes);
			
			String methodName = msg.getMethodName();
			byte[] methodNameBytes = methodName.getBytes();
			out.writeByte(methodNameBytes.length);
			out.writeBytes(methodNameBytes);
			
			//不携带任何的参数(长度为0)
			if (msg.getParamValues() == null) {
				out.writeByte(0); 
				return;
			}
			int paramLen = msg.getParamValues().length;
			out.writeByte(paramLen);
			
			Class<?>[] paramClasses = msg.getParamClasses();
			Object[] paramValues = msg.getParamValues();
			
			for (int i = 0; i < paramLen; i++) {
				Class<?> paramClass = paramClasses[i];
				String paramClassName = paramClass.getName();
				byte[] paramBytes = paramClassName.getBytes();
				out.writeByte(paramBytes.length);
				
				out.writeBytes(paramBytes);
				Object paramValue = paramValues[i];
				
				if (Message.class.isAssignableFrom(paramClass)) {
					out.writeBytes(ParamsUtils.toBuffer((Message)paramValue));
				} else if (isPrimitiveOrString(paramClass)) {
					out.writeBytes(ParamsUtils.toBufferForSimpleType(paramValue));
				} else {
					throw new UnsupportedOperationException("RequestProtoEncoder 只支持【Message, Byte, Short, Integer, Long, Char, Boolean, String】");
				}	
			}
		} catch (Exception e) {
			logger.error("RequestProtoEncoder 传输过程中异常", e);
			e.printStackTrace();
		}
		
	}

	private boolean isPrimitiveOrString(Class<?> classz) {
		if (classz == Byte.class || classz == byte.class){
			return true;
		} else if (classz == Short.class || classz == short.class){
			return true;
		} else if (classz == Long.class || classz == Long.class){
			return true;
		} else if (classz == Boolean.class || classz == boolean.class){
			return true;
		} else if (classz == Float.class || classz == float.class){
			return true;
		} else if (classz == Double.class || classz == double.class){
			return true;
		} else if (classz == Character.class || classz == char.class){
			return true;
		} else if (classz == String.class){
			return true;
		}
		return false;
	}
	
}
